package com.pokermind.dse.exception;

import com.pokermind.model.exception.PokerBusinessException;
import com.pokermind.model.enums.ErrorCode;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;

import jakarta.servlet.http.HttpServletRequest;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;

/**
 * 全局异常处理器
 * 实现6.1-6.3错误处理和日志格式
 * 
 * @author PokerMind Team
 */
@RestControllerAdvice
public class GlobalExceptionHandler {
    
    /**
     * 处理业务异常
     */
    @ExceptionHandler(PokerBusinessException.class)
    public ResponseEntity<Map<String, Object>> handleBusinessException(
            PokerBusinessException ex, HttpServletRequest request) {
        
        ErrorCode errorCode = ex.getErrorCode();
        HttpStatus status = errorCode.getHttpStatus();
        
        Map<String, Object> errorResponse = createErrorResponse(
            errorCode.getCode(), 
            errorCode.getMessage(), 
            ex.getDetails(),
            request
        );
        
        // 记录错误日志
        logError(ex, request, errorResponse);
        
        return new ResponseEntity<>(errorResponse, status);
    }
    
    /**
     * 处理参数验证异常
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, Object>> handleValidationException(
            MethodArgumentNotValidException ex, HttpServletRequest request) {
        
        StringBuilder details = new StringBuilder();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            details.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; ");
        }
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.VALIDATION_FAILED.getCode(),
            ErrorCode.VALIDATION_FAILED.getMessage(),
            details.toString(),
            request
        );
        
        return new ResponseEntity<>(errorResponse, ErrorCode.VALIDATION_FAILED.getHttpStatus());
    }
    
    /**
     * 处理绑定异常
     */
    @ExceptionHandler(BindException.class)
    public ResponseEntity<Map<String, Object>> handleBindException(
            BindException ex, HttpServletRequest request) {
        
        StringBuilder details = new StringBuilder();
        for (FieldError error : ex.getBindingResult().getFieldErrors()) {
            details.append(error.getField()).append(": ").append(error.getDefaultMessage()).append("; ");
        }
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.PARAMETER_BINDING_FAILED.getCode(),
            ErrorCode.PARAMETER_BINDING_FAILED.getMessage(),
            details.toString(),
            request
        );
        
        return new ResponseEntity<>(errorResponse, ErrorCode.PARAMETER_BINDING_FAILED.getHttpStatus());
    }
    
    /**
     * 处理类型转换异常
     */
    @ExceptionHandler(MethodArgumentTypeMismatchException.class)
    public ResponseEntity<Map<String, Object>> handleTypeMismatchException(
            MethodArgumentTypeMismatchException ex, HttpServletRequest request) {
        
        String details = String.format("parameter: %s, value: %s, required_type: %s",
            ex.getName(), ex.getValue(), ex.getRequiredType().getSimpleName());
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.PARAMETER_TYPE_MISMATCH.getCode(),
            ErrorCode.PARAMETER_TYPE_MISMATCH.getMessage(),
            details,
            request
        );
        
        return new ResponseEntity<>(errorResponse, ErrorCode.PARAMETER_TYPE_MISMATCH.getHttpStatus());
    }
    
    /**
     * 处理JSON解析异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResponseEntity<Map<String, Object>> handleJsonParseException(
            HttpMessageNotReadableException ex, HttpServletRequest request) {
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.JSON_PARSE_ERROR.getCode(),
            ErrorCode.JSON_PARSE_ERROR.getMessage(),
            ex.getMostSpecificCause().getMessage(),
            request
        );
        
        return new ResponseEntity<>(errorResponse, ErrorCode.JSON_PARSE_ERROR.getHttpStatus());
    }
    
    /**
     * 处理IllegalArgumentException
     */
    @ExceptionHandler(IllegalArgumentException.class)
    public ResponseEntity<Map<String, Object>> handleIllegalArgumentException(
            IllegalArgumentException ex, HttpServletRequest request) {
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.INVALID_ARGUMENT.getCode(),
            ErrorCode.INVALID_ARGUMENT.getMessage(),
            ex.getMessage(),
            request
        );
        
        return new ResponseEntity<>(errorResponse, ErrorCode.INVALID_ARGUMENT.getHttpStatus());
    }
    
    /**
     * 处理其他运行时异常
     */
    @ExceptionHandler(RuntimeException.class)
    public ResponseEntity<Map<String, Object>> handleRuntimeException(
            RuntimeException ex, HttpServletRequest request) {
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.INTERNAL_SERVER_ERROR.getCode(),
            ErrorCode.INTERNAL_SERVER_ERROR.getMessage(),
            ex.getMessage(),
            request
        );
        
        // 记录严重错误日志
        logError(ex, request, errorResponse);
        
        return new ResponseEntity<>(errorResponse, ErrorCode.INTERNAL_SERVER_ERROR.getHttpStatus());
    }
    
    /**
     * 处理通用异常
     */
    @ExceptionHandler(Exception.class)
    public ResponseEntity<Map<String, Object>> handleGeneralException(
            Exception ex, HttpServletRequest request) {
        
        Map<String, Object> errorResponse = createErrorResponse(
            ErrorCode.UNKNOWN_ERROR.getCode(),
            ErrorCode.UNKNOWN_ERROR.getMessage(),
            ex.getMessage(),
            request
        );
        
        // 记录严重错误日志
        logError(ex, request, errorResponse);
        
        return new ResponseEntity<>(errorResponse, ErrorCode.UNKNOWN_ERROR.getHttpStatus());
    }
    
    /**
     * 创建标准错误响应
     */
    private Map<String, Object> createErrorResponse(String errorCode, String message, 
                                                   String details, HttpServletRequest request) {
        Map<String, Object> response = new HashMap<>();
        response.put("success", false);
        response.put("data", null);
        
        // 错误信息
        Map<String, Object> error = new HashMap<>();
        error.put("code", errorCode);
        error.put("message", message);
        if (details != null && !details.trim().isEmpty()) {
            error.put("details", details);
        }
        response.put("error", error);
        
        // 元数据
        Map<String, Object> meta = new HashMap<>();
        meta.put("timestamp", Instant.now().toString());
        meta.put("request_id", generateRequestId());
        meta.put("path", request.getRequestURI());
        meta.put("method", request.getMethod());
        response.put("meta", meta);
        
        return response;
    }
    

    
    /**
     * 记录错误日志
     */
    private void logError(Throwable ex, HttpServletRequest request, Map<String, Object> errorResponse) {
        Map<String, Object> logEntry = new HashMap<>();
        logEntry.put("timestamp", Instant.now().toString());
        logEntry.put("level", "ERROR");
        logEntry.put("request_id", errorResponse.get("meta"));
        logEntry.put("error", errorResponse.get("error"));
        
        Map<String, Object> requestInfo = new HashMap<>();
        requestInfo.put("method", request.getMethod());
        requestInfo.put("url", request.getRequestURL().toString());
        requestInfo.put("user_agent", request.getHeader("User-Agent"));
        requestInfo.put("remote_addr", request.getRemoteAddr());
        logEntry.put("request", requestInfo);
        
        logEntry.put("exception_class", ex.getClass().getSimpleName());
        logEntry.put("stack_trace", getStackTrace(ex));
        
        // 这里可以集成实际的日志框架（如Logback/Log4j）
        System.err.println("ERROR LOG: " + logEntry);
    }
    
    /**
     * 获取堆栈跟踪信息
     */
    private String getStackTrace(Throwable ex) {
        java.io.StringWriter sw = new java.io.StringWriter();
        java.io.PrintWriter pw = new java.io.PrintWriter(sw);
        ex.printStackTrace(pw);
        return sw.toString();
    }
    
    /**
     * 生成请求ID
     */
    private String generateRequestId() {
        return "req_" + System.currentTimeMillis() + "_" + (int)(Math.random() * 10000);
    }
}